﻿using Abp.Domain.Entities.Auditing;
using Abp.Extensions;
using Abp.UI;
using Microsoft.AspNetCore.Http;
using System;

namespace Mt.Site.Application
{
    public static class AppCheck
    {
        /// <summary>
        /// 乐观锁，验证数据是否过期
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="oldLastModificationTime"></param>
        /// <param name="entity"></param>
        /// <param name="errMsg">友好异常的内容</param>
        public static void CheckLastModificationTime<T>(DateTime? oldLastModificationTime, T entity,string errMsg)
        {
            if (entity is IHasModificationTime)
            {
                var lastModificationTime = entity.As<IHasModificationTime>().LastModificationTime;

                if (oldLastModificationTime != lastModificationTime &&
                    oldLastModificationTime.Value.ToUnixTime() != lastModificationTime.Value.ToUnixTime())
                {
                    throw new UserFriendlyException(errMsg);
                }
            }
        }

        #region Guid

        public static Guid? GetNullableGuidValue(IHttpContextAccessor httpContextAccessor, string parameterName)
        {
            var context = httpContextAccessor.HttpContext;
            if (context != null)
            {
                string value = context.Request.Query[parameterName];
                if (value == null && context.Request.HasFormContentType)
                {
                    value = context.Request.Form[parameterName];
                }
                if (value.IsNullOrEmpty())
                {
                    return null;
                }

                Guid val;
                if (Guid.TryParse(value, out val))
                {
                    return val;
                }
            }

            throw new ArgumentException(parameterName);
        }
        public static Guid GetGuidValue(IHttpContextAccessor httpContextAccessor, string parameterName)
        {
            Guid? val = GetNullableGuidValue(httpContextAccessor, parameterName);
            if (val == null)
            {
                throw new ArgumentException($"{parameterName} can not be null or empty!", parameterName);
            }
            return val.Value;
        }

        #endregion

        #region string

        public static string GetStringValue(IHttpContextAccessor httpContextAccessor, string parameterName,bool required)
        {
            var context = httpContextAccessor.HttpContext;
            if (context != null)
            {
                string value = context.Request.Query[parameterName];
                if (value == null && context.Request.HasFormContentType)
                {
                    value = context.Request.Form[parameterName];
                }
                if (value == "null")
                {
                    value = null;
                }

                if (value.IsNullOrWhiteSpace() && required)
                {
                    throw new ArgumentException($"{parameterName} can not be null, empty or white space!", parameterName);
                }

                return value;
            }

            throw new ArgumentException(parameterName);
        }

        public static string GetStringValue(IHttpContextAccessor httpContextAccessor, string parameterName, bool required, int maxLength)
        {
            var value = GetStringValue(httpContextAccessor, parameterName, required);
            if(value.IsNullOrEmpty())
            {
                return value;
            }

            if (value.Length > maxLength)
            {
                throw new ArgumentException($"The length of {parameterName} must be less than {maxLength}!", parameterName);
            }

            return value;
        }
        #endregion

        #region int

        public static int GetIntegerValue(IHttpContextAccessor httpContextAccessor, string parameterName, bool notZere)
        {
            var context = httpContextAccessor.HttpContext;
            if (context != null)
            {
                string value = context.Request.Query[parameterName];
                if (value == null && context.Request.HasFormContentType)
                {
                    value = context.Request.Form[parameterName];
                }

                if (value.IsNullOrEmpty())
                {
                    if(notZere)
                    {
                        throw new ArgumentException($"{parameterName} can not be null!", parameterName);
                    }
                    return 0;
                }

                int val = 0;
                if (int.TryParse(value, out val))
                {
                    return val;
                }
            }

            throw new ArgumentException(parameterName);
        }


        public static int GetIntegerValue(IHttpContextAccessor httpContextAccessor, string parameterName, int min, int max)
        {
            var context = httpContextAccessor.HttpContext;
            if (context != null)
            {
                string value = context.Request.Query[parameterName];
                if (value == null && context.Request.HasFormContentType)
                {
                    value = context.Request.Form[parameterName];
                }

                int val = 0;
                int.TryParse(value, out val);
                if(val < min || val > max)
                {
                    throw new ArgumentException($"{parameterName} must be less than {max}, greater than {min} !", parameterName);
                }
                return val;
            }

            throw new ArgumentException(parameterName);
        }

        #endregion

        #region long

        public static long GetLongIntegerValue(IHttpContextAccessor httpContextAccessor, string parameterName, bool notZere)
        {
            var context = httpContextAccessor.HttpContext;
            if (context != null)
            {
                string value = context.Request.Query[parameterName];
                if (value == null && context.Request.HasFormContentType)
                {
                    value = context.Request.Form[parameterName];
                }

                if (value.IsNullOrEmpty())
                {
                    if (notZere)
                    {
                        throw new ArgumentException($"{parameterName} can not be zero!", parameterName);
                    }
                    return 0;
                }

                long val = 0;
                if (long.TryParse(value, out val))
                {
                    return val;
                }
            }

            throw new ArgumentException(parameterName);
        }

        public static long GetLongIntegerValue(IHttpContextAccessor httpContextAccessor, string parameterName, long min, long max)
        {
            var context = httpContextAccessor.HttpContext;
            if (context != null)
            {
                string value = context.Request.Query[parameterName];
                if (value == null && context.Request.HasFormContentType)
                {
                    value = context.Request.Form[parameterName];
                }

                long val = 0;
                long.TryParse(value, out val);
                if (val < min || val > max)
                {
                    throw new ArgumentException($"{parameterName} must be less than {max}, greater than {min} !", parameterName);
                }
                return val;
            }

            throw new ArgumentException(parameterName);
        }
        #endregion

        #region float

        public static float GetFloatValue(IHttpContextAccessor httpContextAccessor, string parameterName, bool notZere)
        {
            var context = httpContextAccessor.HttpContext;
            if (context != null)
            {
                string value = context.Request.Query[parameterName];
                if (value == null && context.Request.HasFormContentType)
                {
                    value = context.Request.Form[parameterName];
                }

                if (value.IsNullOrEmpty())
                {
                    if (notZere)
                    {
                        throw new ArgumentException($"{parameterName} can not be zero!", parameterName);
                    }
                    return 0;
                }

                float val = 0;
                if (float.TryParse(value, out val))
                {
                    return val;
                }
            }

            throw new ArgumentException(parameterName);
        }

        public static float GetFloatValue(IHttpContextAccessor httpContextAccessor, string parameterName, float min, float max)
        {
            var context = httpContextAccessor.HttpContext;
            if (context != null)
            {
                string value = context.Request.Query[parameterName];
                if (value == null && context.Request.HasFormContentType)
                {
                    value = context.Request.Form[parameterName];
                }

                float val = 0;
                float.TryParse(value, out val);
                if (val < min || val > max)
                {
                    throw new ArgumentException($"{parameterName} must be less than {max}, greater than {min} !", parameterName);
                }
                return val;
            }

            throw new ArgumentException(parameterName);
        }

        #endregion

        #region double

        public static double GetDoubleValue(IHttpContextAccessor httpContextAccessor, string parameterName, bool notZere)
        {
            var context = httpContextAccessor.HttpContext;
            if (context != null)
            {
                string value = context.Request.Query[parameterName];
                if (value == null && context.Request.HasFormContentType)
                {
                    value = context.Request.Form[parameterName];
                }

                if (value.IsNullOrEmpty())
                {
                    if (notZere)
                    {
                        throw new ArgumentException($"{parameterName} can not be zero!", parameterName);
                    }
                    return 0;
                }

                double val = 0;
                if (double.TryParse(value, out val))
                {
                    return val;
                }
            }

            throw new ArgumentException(parameterName);
        }

        public static double GetDoubleValue(IHttpContextAccessor httpContextAccessor, string parameterName, double min, double max)
        {
            var context = httpContextAccessor.HttpContext;
            if (context != null)
            {
                string value = context.Request.Query[parameterName];
                if (value == null && context.Request.HasFormContentType)
                {
                    value = context.Request.Form[parameterName];
                }

                double val = 0;
                double.TryParse(value, out val);
                if (val < min || val > max)
                {
                    throw new ArgumentException($"{parameterName} must be less than {max}, greater than {min} !", parameterName);
                }
                return val;
            }

            throw new ArgumentException(parameterName);
        }

        #endregion

        #region enum

        public static T GetEnumValue<T>(IHttpContextAccessor httpContextAccessor, string parameterName, bool canBeNull)   where T:struct
        {
            var context = httpContextAccessor.HttpContext;
            if (context != null)
            {
                string value = context.Request.Query[parameterName];
                if (value == null && context.Request.HasFormContentType)
                {
                    value = context.Request.Form[parameterName];
                }

                if (value.IsNullOrEmpty())
                {
                    if (!canBeNull)
                    {
                        throw new ArgumentException($"{parameterName} can not be zero!", parameterName);
                    }

                    return 0.ToEnum<T>();
                }

                int val = 0;
                if (int.TryParse(value, out val))
                {
                    return val.ToEnum<T>();
                }
            }

            throw new ArgumentException(parameterName);
        }

        #endregion

        #region bool
        public static bool? GetNullableBooleanValue(IHttpContextAccessor httpContextAccessor, string parameterName)
        {
            var context = httpContextAccessor.HttpContext;
            if (context != null)
            {
                string value = context.Request.Query[parameterName];
                if (value == null && context.Request.HasFormContentType)
                {
                    value = context.Request.Form[parameterName];
                }

                if (value.IsNullOrEmpty())
                {
                    return null;
                }

                bool val = false;
                if (bool.TryParse(value, out val))
                {
                    return val;
                }
            }

            throw new ArgumentException(parameterName);
        }

        public static bool GetBooleanValue(IHttpContextAccessor httpContextAccessor, string parameterName)
        {
            var val = GetNullableBooleanValue(httpContextAccessor, parameterName);
            if (val == null)
            {
                return false;
            }
            return val.Value;
        }
        #endregion
    }
}
